package cn.jzx.scalademo1

object OOP extends App {


  /*
    //1.
    //定义一个两个参数的构造器Point类
    class Point(xc:Int,yc:Int){
      //成员变量
      var x =xc
      var y = yc

      //无参构造
      def this()={
        this(0,0)
      }

      //成员方法
      def move(dx:Int,dy:Int) ={
        x = x +dx
        y = y + dy
      }
    }

    val p1 = new Point()
    p1.x=10
    println(p1.x)
    p1.move(2,4)

    val p2 = new Point(12,11)

    class BlackPoint() extends Point {
      private var color="black"
      override def move(dx: Int, dy: Int) ={
        x = x + dx
        y = y + dy
        println("moved to x:"+x+" y:"+y)
      }
    }


    abstract class Shape{
      def draw():Unit
    }

    class Square extends Shape{
      override def draw():Unit={
        println("draw a square")
      }
    }
  */


  /*
    //2.调用LikeStatic类
    LikeStatic.foo
    LikeStatic.foo
  */


  /*
    //3.
    //Student.scala
    //伴生类

    // 没有new
     val stu1 = Student("abc",17)
     println(stu1)
  */


  /*
    //4.book类(样例类)
    val books: List[Book] = List(Book("逆天邪神", "火星引力"), Book("生肖守护神", "唐家三少"),
      Book("斗罗大陆", "唐家三少")
    )
    println(books.size)


    // java == 是运算符 scala == 是函数
    books.filter(book => book.author == new String("唐家三少")).foreach(println(_))
  */


  /*
    //5.混入特质
    abstract class A {
      val message: String
    }
    class B extends A {
      val message = "I'm an instance of class B"
    }
    trait C extends A {
      def loudMessage = {

         message.toUpperCase()

      }
    }
    class D extends B with C

    val d = new D
    println(d.message)  // I'm an instance of class B
    println(d.loudMessage)  // I'M AN INSTANCE OF CLASS B
  */


  /*
    //6.动态混入
    class Drawing {
      // ???
      self: Shape =>
      def start(): Unit = draw()
    }

    trait Shape {
      def draw(): Unit
    }

    trait Square extends Shape {
      def draw(): Unit = println("draw a square")
    }

    trait Triangle extends Shape {
      def draw(): Unit = println("draw a triangle")
    }

    //动态混入
    (new Drawing() with Square).start()
    (new Drawing() with Triangle).start()
  */


  /*
    //7.为Book混入Ebook特质
    class Book {
      self: EBook =>
      def start() = play()
    }

    trait EBook {
      def play(): Unit
    }

    trait Pc extends EBook {
      override def play(): Unit = println("1980*1080")
    }

    trait Phone extends EBook {
      override def play(): Unit = println("765*438")
    }

    trait Pad extends EBook {
      override def play(): Unit = println("1024*768")
    }

    (new Book() with Pad).start()
  */


  /*
    //8.为Book混入Ebook特质(静态混入)
    abstract class Book {
      def play(): Unit
    }

    trait EBook extends Book {
      def start() = play()
    }

    class Pc extends Book with EBook {
      override def play(): Unit = println("pc...........")
    }

    class Pad extends Book with EBook {
      override def play(): Unit = println("pad.......")
    }

    new Pc().start()
  */


  /*
    //9.
    trait Person

    case class Student(name: String, age: Int) extends Person

    case class Teacher(name: String, age: Int) extends Person

    class GrilStudent(override val name: String, override val age: Int, height: Double) extends Student(name, age) {
      val gheight = height

      def this() = {
        this("", 0, 0.0)
      }
    }

    object GrilStudent {
      def apply(name: String, age: Int, height: Double): GrilStudent = new GrilStudent(name, age, height)

      /*    //动态参数 apply 方法
          def apply(arg: Any*): GrilStudent = {
            if (arg == null || arg.length == 0) {
              new GrilStudent()
            } else {
              new GrilStudent(arg(0).toString, arg(1).asInstanceOf[Int], arg(2).asInstanceOf[Double])
            }

          }*/

      // TypeScript 支持 泛型 或
      def unapply(arg: GrilStudent): Option[(String, Int, Double)] = if (arg == null) None else Some(arg.name, arg.age, arg.gheight)
    }

    /*
      class GrilStudent(name: String, age: Int, height: Double) extends Person {
        val gname = name
        val gage = age
        val gheight = height
      }

      object GrilStudent {
        def apply(name: String, age: Int, height: Double): GrilStudent = new GrilStudent(name, age, height)

        def unapply(arg: GrilStudent): Option[(String, Int, Double)] = if (arg == null) None else Some(arg.gname, arg.gage, arg.gheight)
      }
    */

    //样例类的模式匹配
    def matchTest4(x: Person) = x match {
      case Student(name, 19) => println(name)
      case Student("Tom", age) => println(age)
      case GrilStudent(name, age, height) => println(name, age, height)
      case Student(name, age) => println(name, age)
      case _ => println("no matches")
    }

    matchTest4(Student("Jason", 19))
    matchTest4(Student("Tom", 20))
    matchTest4(Student("Jimmy", 20))
    //  matchTest4(Teacher("java", 27))
    matchTest4(GrilStudent("Jimmy", 21, 1.88))
    //  matchTest4(GrilStudent())
  */


  /*
    //10.枚举类
    /*
      //val day=? if(day=="Monday")
      object Weekday extends Enumeration {
        type Weekday = Value
        val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
      }
      // println(Weekday.Fri.toString)
      Weekday.values.foreach(println(_))
    */

    abstract class Term(code: String)

    case class Var(name: String) extends Term(name)

    case class Fun(arg: String, body: Term) extends Term(arg)

    case class App(f: Term, v: Term) extends Term("App")

    val v = Var("java")
    val f = Fun("foo", v)
    val a1 = App(v, f)
    val a2 = App(f, a1)
    val a3 = App(a2, a2)

    println(a2)

    def printEveryOne(t: Term): Unit = t match {
      case Var(name) => {
        println("Var ...")
        println(s"name=$name")
      }
      case Fun(arg, body) => {
        println("---------Fun  start------------")
        println(s"arg=$arg")
        printEveryOne(body)
        println("---------Fun  end------------")
      }
      case App(f, v) => {
        println("---------App  start------------" + f + "|" + v)
        printEveryOne(f)
        printEveryOne(v)
        println("---------App  end------------" + f + "|" + v)
      }
      case _ => println("no match....")
    }

    println(a2)
    printEveryOne(a2)
  */

  //11.
  class A
    class B extends A
    class C extends B

    class Op1[T <: B] {
      def foo(x:T)=println(x)
    }

  val o1=new Op1[B]
  val a=new C()

  o1.foo(a)

}